import React, { useState } from 'react';
import { Icon, Col, Row, Button, Modal, Empty, Tag, Tooltip, message } from 'antd';
import { connect } from 'dva';
import {
  Form,
  FormItem,
  createFormActions,
  FormEffectHooks,
  InternalFieldList as FieldList,
  FormPath,
} from '@formily/antd';
import { Select, Input } from '@formily/antd-components';
import omit from 'lodash/omit';
import classNames from 'classnames';
import useCopyToClipboard from '@/hooks/useCopyToClipboard';
import ScrollBar from '@/components/ScrollBar';
import { firstUpperCase, closest } from '@/utils/utils';
import { getAllFieldName } from './utils';
import styles from '../styles.less';

const actions = createFormActions();
const { onFieldValueChange$ } = FormEffectHooks;

function LinkageRule({ dispatch, formSchema, linkages, container }) {
  const [visible, setVisible] = useState(false);
  const [state, copyToClipboard] = useCopyToClipboard();

  // function confirm() {
  //   Modal.confirm({
  //     title: '配置联动规则将冻结表单模板',
  //     content: '确定已完成表单模板配置了吗？',
  //     okText: '开始配置',
  //     cancelText: '取消',
  //     onOk: () => setVisible(true),
  //   });
  // }

  return (
    <>
      <Modal
        getContainer={container.current}
        title={
          <>
            联动规则
            <Tooltip
              getPopupContainer={trigger => closest(trigger, '.ant-modal-header')}
              overlayClassName={styles.introduce}
              placement="bottomLeft"
              title={
                <div>
                  <p>
                    <b>规则面板（左侧）</b>
                  </p>
                  <ul>
                    <li>
                      <span>
                        <b>条件</b>或<b>计算表达式</b>支持
                      </span>
                      ： <span className={styles.code}>+</span>
                      <span className={styles.code}>-</span>
                      <span className={styles.code}>*</span>
                      <span className={styles.code}>/</span>
                      <span className={styles.code}>&#62;</span>
                      <span className={styles.code}>&#60;</span>
                      <span className={styles.code}>&#61;&#61;</span>
                      <span className={styles.code}>&#33;&#61;</span>
                      <span className={styles.code}>&#62;&#61;</span>
                      <span className={styles.code}>&#60;&#61;</span>
                      <span className={styles.code}>and</span>
                      <span className={styles.code}>or</span>
                      <span className={styles.code}>in</span>
                      <span className={styles.code}>x ? y : z</span>
                      <span className={styles.code}>post</span>
                      <span className={styles.code}>get</span>
                      {/* +，-，*，/，>，<，==，!=，>=，<=，and，or，in，三元表达式（x ? y : z），post和get请求 */}
                    </li>
                    <li>
                      <span className={styles.code}>post</span>和
                      <span className={styles.code}>get</span>
                      表示异步请求，仅适用于【设置选项】的计算表达式。
                    </li>
                    <li>
                      表达式中的<b>字段名</b>表示它的值
                    </li>
                    <li>
                      表达式中描述字符串，请使用双引号，例如: price == &quot;20&quot;。
                      <b className="text-danger">不支持单引号</b>
                    </li>
                  </ul>
                  <p>
                    <b>字段面板（右侧）</b>
                  </p>
                  <ul>
                    <li>
                      点击复制字段名，用于
                      <b>条件</b>或<b>计算表达式</b>
                    </li>
                  </ul>
                  <p>
                    <b>注意事项：</b>
                  </p>
                  <ul>
                    <li>更改规则后，请点击【保存】</li>
                  </ul>
                </div>
              }
            >
              <a className="ant-dropdown-link margin-left-lg" style={{ fontSize: 12 }}>
                操作说明
                <Icon type="down" />
              </a>
            </Tooltip>
          </>
        }
        destroyOnClose
        visible={visible}
        width={1100}
        centered
        okText="保存"
        onOk={() => {
          setVisible(false);
          actions.submit();
          message.success('保存成功');
        }}
        onCancel={() => setVisible(false)}
        bodyStyle={{ minHeight: 448 }}
      >
        <Form
          className={classNames('flow', styles.labelBold)}
          actions={actions}
          colon={false}
          effects={({ setFieldState }) => {
            // 监听：checked时，展示对应的输入框
            onFieldValueChange$('linkages.*.driveType').subscribe(({ name, value }) => {
              if (value === 'calc' || value === 'setOptions') {
                setFieldState(
                  FormPath.transform(name, /\d/, $1 => {
                    return `linkages.${$1}.targetEleRuleExpr`;
                  }),
                  state => {
                    state.visible = value;
                  }
                );
              } else {
                setFieldState(
                  FormPath.transform(name, /\d/, $1 => {
                    return `linkages.${$1}.targetEleRuleExpr`;
                  }),
                  state => {
                    state.visible = false;
                  }
                );
              }
            });
          }}
          onSubmit={() => {
            // TODO: 表达式语法校验，比如设置值的表达式不允许出现post或get请求；字符串使用双引号（单引号无效）
            dispatch({
              type: 'formDesigner/update',
              payload: { ...actions.getFormState().values },
            });
          }}
        >
          <FieldList name="linkages" initialValue={linkages}>
            {({ state, mutators }) => {
              const onAdd = () => mutators.push();
              const onRemove = index => mutators.remove(index);
              return (
                <div>
                  {state.value.length === 0 ? (
                    <Empty
                      style={{ marginTop: 150 }}
                      description={
                        <>
                          <Button type="link" icon="plus" onClick={onAdd}>
                            开始配置
                          </Button>
                        </>
                      }
                    />
                  ) : (
                    <div className="media-box">
                      <div
                        className={classNames('media-right', styles.linkagesHelp)}
                        style={{ height: 400 }}
                      >
                        <ScrollBar
                          renderView={({ style, ...props }) => {
                            const viewStyle = {
                              padding: '0 16px 0 0',
                            };
                            return <div style={{ ...style, ...viewStyle }} {...props} />;
                          }}
                        >
                          {getAllFieldName(formSchema).length > 0
                            ? getAllFieldName(formSchema).map(item => (
                                // eslint-disable-next-line react/jsx-indent
                                <Tag
                                  key={item.value}
                                  className={classNames({
                                    mark: Array.isArray(item.dataSource),
                                  })}
                                  onClick={() => {
                                    copyToClipboard(item.value);
                                  }}
                                >
                                  {item.dataSource ? (
                                    <Tooltip
                                      getPopupContainer={() => container.current}
                                      title={
                                        <>
                                          <p>组件：{item.componentType}</p>
                                          {item.dataSource.map(obj => (
                                            <p key={obj.value}>
                                              {`${obj.label}：${obj.value} <${firstUpperCase(
                                                typeof obj.value
                                              )}>`}
                                            </p>
                                          ))}
                                        </>
                                      }
                                    >
                                      {item.label}
                                    </Tooltip>
                                  ) : (
                                    item.label
                                  )}
                                </Tag>
                              ))
                            : null}
                        </ScrollBar>
                      </div>
                      <div className="media-body">
                        <div className="media-body-text-hack" />
                        <div style={{ height: 400 }}>
                          <ScrollBar
                            renderView={({ style, ...props }) => {
                              const viewStyle = {
                                padding: '0 16px 0 0',
                              };
                              return <div style={{ ...style, ...viewStyle }} {...props} />;
                            }}
                          >
                            {state.value.map((item, index) => (
                              <div key={index} className="margin-bottom-lg">
                                <h3>
                                  <div className="pull-right">
                                    <Button
                                      type="link"
                                      className={classNames('margin-right', 'text-danger')}
                                      style={{ padding: 0 }}
                                      onClick={() => {
                                        onRemove(index);

                                        // dispatch({
                                        //   type: 'formDesigner/update',
                                        //   payload: { linkages: update(list, { $splice: [[index, 1]] }) },
                                        // });
                                      }}
                                    >
                                      删除
                                    </Button>
                                    <Button type="link" style={{ padding: 0 }} onClick={onAdd}>
                                      添加
                                    </Button>
                                  </div>
                                  {`#${index + 1}`}
                                </h3>
                                <Row gutter={16}>
                                  <Col span={10}>
                                    <FormItem
                                      label="规则名称"
                                      placeholder="请选择"
                                      rules={[{ required: true, message: '必填字段' }]}
                                      allowClear
                                      name={`linkages.${index}.ruleName`}
                                      triggerType="onChange"
                                      component={Input}
                                    />
                                  </Col>
                                  <Col span={8}>
                                    <FormItem
                                      label="目标字段"
                                      placeholder="请选择"
                                      rules={[{ required: true, message: '必填字段' }]}
                                      allowClear
                                      name={`linkages.${index}.targetEleCode`}
                                      triggerType="onChange"
                                      component={Select}
                                      getPopupContainer={trigger =>
                                        closest(trigger, '.ant-modal-body')
                                      }
                                      dataSource={getAllFieldName(formSchema).map(item =>
                                        omit(item, ['dataSource', 'componentType'])
                                      )}
                                    />
                                  </Col>
                                  <Col span={6}>
                                    <FormItem
                                      label="动作类型"
                                      placeholder="请选择"
                                      rules={[{ required: true, message: '必填字段' }]}
                                      allowClear
                                      name={`linkages.${index}.driveType`}
                                      triggerType="onChange"
                                      component={Select}
                                      getPopupContainer={trigger =>
                                        closest(trigger, '.ant-modal-body')
                                      }
                                      dataSource={[
                                        { label: '隐藏', value: 'hide' },
                                        { label: '显示', value: 'show' },
                                        { label: '设置值', value: 'calc' },
                                        { label: '设置选项', value: 'setOptions' },
                                        { label: '设置必填', value: 'required' },
                                        { label: '设置非必填', value: 'notRequired' },
                                      ]}
                                    />
                                  </Col>
                                  <Col span={24}>
                                    <FormItem
                                      label="触发条件"
                                      rules={[{ required: true, message: '必填字段' }]}
                                      allowClear
                                      placeholder="条件表达式"
                                      name={`linkages.${index}.triggerEleRuleExpr`}
                                      triggerType="onChange"
                                      component={Input}
                                    />
                                  </Col>
                                  <Col span={24}>
                                    <FormItem
                                      label="计算公式"
                                      rules={[{ required: true, message: '必填字段' }]}
                                      allowClear
                                      placeholder="计算表达式"
                                      name={`linkages.${index}.targetEleRuleExpr`}
                                      triggerType="onChange"
                                      visible={false}
                                      component={Input}
                                    />
                                  </Col>
                                </Row>
                              </div>
                            ))}
                          </ScrollBar>
                        </div>
                      </div>
                    </div>
                  )}
                </div>
              );
            }}
          </FieldList>
        </Form>
      </Modal>
      {/* <Button type="link" icon="plus" onClick={confirm} style={{ padding: 0 }}> */}
      <Button
        type="link"
        icon="plus"
        onClick={() => setVisible(true)}
        style={{ padding: 0 }}
        disabled={formSchema.length === 0}
      >
        联动规则
      </Button>
    </>
  );
}

export default connect(({ formDesigner }) => ({
  formSchema: formDesigner.formSchema,
  linkages: formDesigner.linkages,
}))(LinkageRule);
